<!--
 * @Title:
 * @Descripttion:
 * @Version: 2.0
 * @Author: tangyong
 * @Date: 2025-04-08 13:48:15
 * @LastEditors: weidewei
 * @LastEditTime: 2025-07-02 15:25:31
-->
<template>
  <div class="comp-dynamic-table">
    <el-form ref="formInstance" :model="formData" @submit.prevent>
      <table ref="tableRef" class="el-table-simple">
        <tbody>
          <tr v-for="(item, index) in tableHeaderRules" :key="index">
            <td
              @dblclick="handleDoubleClick(col)"
              v-for="(col, idx) in item"
              :class="{ 'is-operate-column': col.value === '操作' }"
              :key="idx"
              :colspan="col.colSpan"
              :rowspan="col.rowSpan"
              :style="getTdStyle(col.colObj)"
            >
              <span :style="getShowStyle(col.colObj)" v-if="col.type === 'text'" class="cell-span">
                {{ col.value }}
                <el-tooltip
                  v-if="col.tipContent"
                  effect="dark"
                  :content="col.tipContent"
                  raw-content
                  placement="right"
                >
                  <el-icon color="#E6A23C"><Opportunity /></el-icon>
                </el-tooltip>
              </span>
            </td>
          </tr>
          <tr>
            <td
              @dblclick="handleDoubleClick(col)"
              v-for="(col, idx) in tableColumns"
              :class="{ 'is-operate-column': col.type === 'link' }"
              :key="idx"
              :colspan="col.colSpan"
              :rowspan="col.rowSpan"
              :style="getTdStyle(col.colObj)"
            >
              <el-form-item :prop="`tableData.${index}.${col.prop}`">
                <!-- 纯文本 -->
                <span v-if="col.type === 'text'" class="cell-span">
                  {{ col.value }}
                </span>
                <!-- 输入框 -->
                <el-input v-else v-bind="getColumnProps(col)" @click.stop />
              </el-form-item>
            </td>
          </tr>
        </tbody>
      </table>
    </el-form>
    <component
      v-if="dialogStatus"
      :is="componentName"
      :action="action"
      :dialog-data="dialogData"
      v-model:dialog-status="dialogStatus"
      @dialog-confirm="handleConfirm"
    />
  </div>
</template>
<script lang="ts" setup>
  import { isEmptyObj, isEmpty } from "@utils/index";
  import { Opportunity } from "@element-plus/icons-vue";
  import { cloneDeep } from "lodash-es";
  const DialogByFieldOperate = defineAsyncComponent(() => import("./DialogByFieldOperate.vue"));
  const props = defineProps({
    rules: {
      type: Array,
      default: () => [],
    },
    data: {
      type: Array,
      default: () => [],
    },
    startRow: {
      type: Number,
      default: 1,
    },
    canEdit: {
      type: Boolean,
      default: true,
    },
  });

  const { proxy } = getCurrentInstance()!;

  const formInstance: any = shallowRef(null);
  const formData: any = ref({
    tableData: [],
  });
  const tableHeaderRules: any = ref([]);
  const tableColumns: any = ref([]);
  const dialogStatus = ref(false);
  const action: any = ref("");
  const componentName: any = shallowRef();
  const dialogData: any = shallowRef(null);
  watch(
    () => props.rules,
    (arr) => {
      if (!Array.isArray(arr) || !arr.length) return;
      nextTick(() => {
        initRules();
      });
    },
    { immediate: true },
  );

  function initRules() {
    let originRules = cloneDeep(props.rules);
    const exposed: any = proxy?.$.exposed;
    originRules.forEach((item: any) => {
      item.on = {
        change: () => {
          nextTick(() => {
            dispatchEvent();
          });
        },
      };
      if (Array.isArray(item.validate) && item.validate.length) {
        item.validate.forEach((it) => {
          if (it.type === "fn") {
            it.validator =
              typeof exposed[it.validator] === "function" ? exposed[it.validator] : function () {};
          }
        });
      }
    });
    // const groupRules: any = originRules.reduce((acc: any, cur: any) => {
    //   console.log("acc",acc);
    //   console.log("cur",cur);
    //   if (cur.startRow) {
    //     acc.push([cur]);
    //   } else {
    //     acc[acc.length - 1].push(cur);
    //   }
    //   return acc;
    // }, []);
    const groupRules = (originRules) => {
      return originRules.reduce((acc, cur) => {
        const cellRow = cur.colObj.cellRow;
        if (!acc[cellRow]) {
          acc[cellRow] = []; // 如果该行不存在，初始化一个空数组
        }
        acc[cellRow].push(cur); // 将当前项推入对应的行数组
        return acc;
      }, {});
    };

    const groupedData = groupRules(originRules);
    const resultData = Object.values(groupedData); // 转换为二维数组
    // 分离静态表头与动态数据表头
    tableHeaderRules.value = resultData.slice(0, props.startRow);
    const _tableColumns = resultData.slice(props.startRow);
    tableColumns.value = Array.isArray(_tableColumns) ? _tableColumns[0] : [];
    formData.value.tableData = cloneDeep(props.data);
  }

  function getRule(col) {
    if (Array.isArray(col.validate) && col.validate.length) return col.validate;
    return [];
  }

  function getColumnProps(column) {
    return typeof column.props === "object" ? column.props : {};
  }

  function getColumnEvents(column) {
    if (isEmptyObj(column.on)) return {};
    const tempEvt = {};
    Object.keys(column.on).forEach((evtName) => {
      tempEvt[evtName] = column.on[evtName];
    });
    return tempEvt;
  }

  function dispatchEvent() {
    formInstance.value.clearValidate();
    props.rules.forEach((item: any) => {
      if (Array.isArray(item.emit) && item.emit.length) {
        item.emit.forEach((it) => {
          if (it.fnName === "excuteFormula") {
            excuteFormula(it.params, item.prop);
          }
        });
      }
    });
  }

  function excuteFormula(params, prop?) {
    if (isEmpty(params?.express)) return;
    const exp = params.express.replace(/{([^}]+)\}/g, (_a, b) => {
      return +formData.value[b] || 0;
    });
    try {
      const ret = eval(exp);
      if (!isEmpty(prop)) {
        formData.value[prop] = ret;
      }
      return ret;
    } catch (e) {
      console.log(e);
    }
  }

  // 比较相等
  function comppareEqual(rule, _val, cb) {
    const ret = excuteFormula(rule.params);
    if (ret == null || isEmpty(cb)) return cb();
    if (ret !== 0) {
      cb(new Error(rule.message));
    } else {
      cb();
    }
  }

  // 比较不等
  function compareUnequal(rule, _val, cb) {
    const ret = excuteFormula(rule.params);
    if (ret == null || isEmpty(cb)) return cb();
    if (ret === 0) {
      cb(new Error(rule.message));
    } else {
      cb();
    }
  }

  // 比较大于或等于
  function compareGreaterThanOrEqual(rule, _val, cb) {
    const ret = excuteFormula(rule.params);
    if (ret == null || isEmpty(cb)) return cb();
    if (ret < 0) {
      cb(new Error(rule.message));
    } else {
      cb();
    }
  }

  // 比较是否小于1
  function compareLessThanOne(rule, _val, cb) {
    const ret = excuteFormula(rule.params);
    if (ret == null || isEmpty(cb)) return cb();
    if (ret >= 1) {
      cb(new Error(rule.message));
    } else {
      cb();
    }
  }
  // 行删除
  // function handleRowDeleteClick(index) {
  //   confirm(() => {
  //     formData.value.tableData.splice(index, 1);
  //   });
  // }

  // 行新增
  // function handleRowAddClick() {
  //   formData.value.tableData.push({});
  // }

  // function validate() {
  //   return new Promise((resolve) => {
  //     formInstance.value.validate((valid) => {
  //       if (valid) {
  //         resolve(cloneDeep(formData.value));
  //       } else {
  //         resolve(false);
  //       }
  //     });
  //   });
  // }

  function handleDoubleClick(col) {
    console.log("col2", col);
    if (isEmptyObj(col)) return;
    dialogStatus.value = true;
    componentName.value = DialogByFieldOperate;
    dialogData.value = col.colObj;
    action.value = "edit";
  }

  function getShowStyle(colObj) {
    try {
      return colObj.cellStyle ? JSON.parse(colObj.cellStyle) : {};
    } catch {
      return {}; // 解析失败时返回空对象
    }
  }

  function getTdStyle(colObj) {
    return {
      width: colObj.colWidth || "150px",
      minWidth: colObj.colWidth || "150px",
      maxWidth: colObj.colWidth || "150px",
      height: colObj.rowHeight || "auto",
      minHeight: colObj.rowHeight || "auto",
      maxHeight: colObj.rowHeight || "auto",
    };
  }

  defineExpose({
    excuteFormula,
    comppareEqual,
    compareUnequal,
    compareGreaterThanOrEqual,
    compareLessThanOne,
  });
</script>

<style lang="scss" scoped>
  table {
    table-layout: auto;
  }
  .el-table-simple {
    tbody {
      border-top: 1px solid #e3e8ee;

      .is-operate-column {
        width: 90px;
        text-align: center;
      }
    }

    :deep(.el-form-item) {
      margin-bottom: 0;

      .el-form-item__content {
        .cell-span {
          width: 100%;
          padding: 5px 0;
          line-height: 18px;
        }
        .el-link {
          width: 100%;
        }
      }
    }
  }
</style>
